package com.video;
/*
 * @author：周洋帆
 * @description：根据获取的视频列表进行再排序，再排序运用的是DivRank算法。
 *     DivRank算法的原理是将需要再排序的节点构成一张图。图的顶点用各个节点表示，图边与边之间的权重
 *     由节点本身的特征决定（自己制定规则。）并依照权重的归一化结果作为转移概率，则整个图变成一个马尔科夫
 *     链，经过很多次转移后趋向平稳，这是各节点概率大的就排序靠前，否则靠后。
 *     ps：每次转移概率不是定值，而是由权重和这个节点本身比重，以及一个随机的跳转三者共同决定的。正是这个转移概率
 *     的规定，保证了DivRank算法的分散性。
 * @param
 *     pTrans：由视频列表构成一张图，图上各节点（视频）之间的联系用pTrans[i][j]表示。
 *     list1：优酷返回的视频搜索结果列表。
 *     list2：土豆返回的视频搜索结果列表。
 *     a，d：DivRank算法使用的参数，一般默认a=0.25，d=0.8；
 *     p：每一个视频节点的概率（p[i]表示第i个节点）。最终p的结果决定了节点的排名。
 *     iterators：迭代次数，一般迭代一定次数后马尔科夫链就会收敛。
 * @see
 *     compute（a，d，commend）：
 *         参数：a，d为DivRank参数，一般默认a=0.25，d=0.8。commmend为
 *         数据来源，当commend为youku时，则对优酷获取的结果进行再排序，如果commend为tudou是，
 *         则对土豆获取的结果进行再排序。
 *         
 *         排序的具体方法是：
 *         1，现将list和commend参数传入计算函数中，通过调用initialP方法获取p*，通过
 *             initialTrans方法获取pTrans方法。
 *         2，按照Divrank算法进行运算。
 *         3，将重排序的top5的结果的id返回。
 *         
 *     execute方法：
 *         1，执行compute方法，获取top结果的id
 *         2，在list中根据top结果的id将最终结果取出来，存在指定的返回结果格式中，并返回结果。
 * 
 * @return
 *     compute方法：
 *         返回结果为排名靠前结果的id，是一个整数数组。以id为下标便可以在list中将具体结果取出。
 *     execute方法：
 *         返回指定格式的结果，用于在页面显示的原始数据。
 */
import java.util.*;

public class DivRank {
	private double[][]pTrans=null;
	private List<YoukuInfo> list1=null;
	private List<TudouInfo> list2=null;
	private int number;

	private double[] p;
	double a=0.25,d=0.8;
	int iterators=300;
	
/*	public static void main(String[] args) {
		DivRank div=new DivRank();
		List<Integer> result=div.compute(0.8,0.75);
//		div.printResult(result);
	}*/
	
	public DivRank(List<YoukuInfo> list1,List<TudouInfo> list2){
		this.list1=list1;
		this.list2=list2;	
	}
	
	
	public List<ResultSet> execute(String commend){
		
		if(commend.equals("youku")){
			number=SearchAction.youkuNumber;
		}
		if(commend.equals("tudou")){
			number=SearchAction.tudouNumber;
		}
		p=new double[number];
		
		List<ResultSet>result=new ArrayList<ResultSet>();
		List<Integer> resultRank=compute(a,d,commend);
//		List<Integer> tudou=compute(a,d,"tudou");
		if(commend.equals("youku")){
			for(int i=0;i<resultRank.size();i++){
				ResultSet rs=new ResultSet();
				
				rs.picUrl=list1.get(resultRank.get(i)).getCaptureUrl();
				rs.title=list1.get(resultRank.get(i)).getVideoName();
				rs.videoUrl=list1.get(resultRank.get(i)).getVideoUrl();
				result.add(rs);			
			}		
		}
		if(commend.equals("tudou")){
			for(int i=0;i<resultRank.size();i++){
				ResultSet rs=new ResultSet();
				
				rs.picUrl=list2.get(resultRank.get(i)).getCaptureUrl();
				rs.title=list2.get(resultRank.get(i)).getVideoName();
				rs.videoUrl=list2.get(resultRank.get(i)).getVideoUrl();
				result.add(rs);			
			}
		}
		
		
		return result;
		
	}
	

	
	public List<Integer> compute(double a,double d,String commend){
		List<Integer> result=new ArrayList<Integer>();
		ComputeInitial c=new ComputeInitial(list1,list2,commend);
		double[] preference=c.initialP();//获取p*
		double[][] trans=c.initialTrans(a);//获取转移概率。
		//初始化概率，1/N
		if(commend.equals("tudou")){
//			System.out.println("初始概率");
			String initP="",initTrans="";
			for(int i=0;i<number;i++){
				initP=initP+preference[i]+"\t";
				if(i%10==0)
					initP=initP+"\n";
			}
//			System.out.println(initP);
//			System.out.println("初始转移概率");
			for(int i=0;i<number;i++){
				double temp=0;
				for(int j=0;j<number;j++){
					temp+=trans[i][j];
					if(i==36);
//						System.out.println("error id:  "+temp);
				}
				
					
			    
					
				
			}
					
		}
		for(int i=0;i<number;i++){
			p[i]=1.0/number;
		}
		double[] newP=new double[number];
		for(int iter=1;iter<iterators;iter++){
			
			for(int v=0;v<number;v++){
				double pt=0;
				for(int u=0;u<number;u++){
					double dU=0.0;
					for(int v1=0;v1<number;v1++){
						dU+=trans[u][v1]*p[v1];
					}
			        pt=((trans[u][v]*p[v]+0.0)/dU)*p[u]+pt;
				}
				newP[v]=(1-d)*preference[v]+d*pt;
//				System.out.println(newP[v]);
			}
			p=newP;
			
		}
		int count=0;
		double max=0,temp,sum=0;		
		int id=0;
		for(int j=0;j<5;j++){
			max=0;
			for(int i=0;i<number;i++){
				
				if(p[i]>max){
					id=i;
					max=p[i];
				}
				
			}
            
			p[id]=0;
			result.add(id);
			
		}
		return result;
	}
	
	
	
	
}
